package com.zhtkj.service;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.LocalTime;
import org.joda.time.Seconds;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhtkj.constant.AccessData;
import com.zhtkj.constant.Constant;
import com.zhtkj.constant.FenceConstant;
import com.zhtkj.dto.BoxState;
import com.zhtkj.dto.CarAnalysis;
import com.zhtkj.dto.EcuException;
import com.zhtkj.dto.IllegalBucket;
import com.zhtkj.dto.IllegalWork;
import com.zhtkj.dto.InRestrictArea;
import com.zhtkj.dto.MoveAndNoSpeed;
import com.zhtkj.dto.OutBound;
import com.zhtkj.dto.OverSpeed;
import com.zhtkj.dto.SpeedAndNoMove;
import com.zhtkj.entity.mongo.CarHistory;
import com.zhtkj.entity.zhatu.AutoAnalysisdata;
import com.zhtkj.entity.zhatu.Consapp;
import com.zhtkj.entity.zhatu.Gpsfence;
import com.zhtkj.entity.zhatu.UnloadingArea;
import com.zhtkj.mapper.zhatu.AutoAnalysisdataMapper;
import com.zhtkj.mapper.zhatu.ConsappMapper;
import com.zhtkj.mapper.zhatu.GpsfenceMapper;
import com.zhtkj.mapper.zhatu.UnloadingAreaMapper;
import com.zhtkj.util.GeoUtil;
import com.zhtkj.util.Point;

/** 
* @ClassName: AnalysisService 
* @Description: 违规具体分析对象 
* @author mafeng 
* @date 2017年9月7日 上午9:49:05 
*  
*/
@Service
public class AnalysisService {

	private static Logger logger = Logger.getLogger(AnalysisService.class);
	
	@Autowired
	private AutoAnalysisdataMapper autoAnalysisdataMapper;

	@Autowired
	private ConsappMapper consappMapper;
	
	@Autowired
	private UnloadingAreaMapper unloadingAreaMapper;
	
	@Autowired
	private GpsfenceMapper gpsfenceMapper;
	
	//超速分析
	@Transactional(propagation = Propagation.NEVER)
	public void overSpeedAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		OverSpeed overSpeed = carAnalysis.getOverSpeed();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			
			//如果前一个点和当前点均不为空且速度小于100km/h才开始判断是否超速
			if (prevCarHistory != null && currCarHistory != null &&
				prevCarHistory.getGpsSpeed() < 110 && prevCarHistory.getGpsSpeed() < 110) {
				Float overSpeedValuePrev = Constant.overSpeedValue_default;
				Float overSpeedValueCurr = Constant.overSpeedValue_default;
				Point prevPoint = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
				Point currPoint = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY()); 
				if (GeoUtil.containsPoint(FenceConstant.secondLoopLine, prevPoint)) { // 如果在二环内
					overSpeedValuePrev = Constant.overSpeedValue_erhuan;
				} else if (!GeoUtil.containsPoint(FenceConstant.secondLoopLine, prevPoint) && // 如果在二环和三环之间
						GeoUtil.containsPoint(FenceConstant.thirdLoopLine, prevPoint)) {
					overSpeedValuePrev = Constant.overSpeedValue_sanhuan;
				}
				if (GeoUtil.containsPoint(FenceConstant.secondLoopLine, currPoint)) { // 如果在二环内
					overSpeedValueCurr = Constant.overSpeedValue_erhuan;
				} else if (!GeoUtil.containsPoint(FenceConstant.secondLoopLine, currPoint) && 
						GeoUtil.containsPoint(FenceConstant.thirdLoopLine, currPoint)) { // 如果在二环和三环之间
					overSpeedValueCurr = Constant.overSpeedValue_sanhuan;
				}
				
				// 如果如果前一个点没超速且后一个点超速了
				if (prevCarHistory.getGpsSpeed() < overSpeedValuePrev && 
						currCarHistory.getGpsSpeed() > overSpeedValueCurr) {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
					overSpeed.setAutoAnalysisdata(autoAnalysisdata);
					overSpeed.setStartHistory(currCarHistory);
					overSpeed.setTotal(1);
				} else if (prevCarHistory.getGpsSpeed() > overSpeedValuePrev && // 如果前后点均超速了
					       currCarHistory.getGpsSpeed() > overSpeedValueCurr) {
					if (overSpeed.getAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = overSpeed.getAutoAnalysisdata();
						Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
						Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + GeoUtil.getDistance(p1, p2).intValue());
						if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					overSpeed.setTotal(overSpeed.getTotal() + 1);
				} else if (prevCarHistory.getGpsSpeed() > overSpeedValuePrev && // 如果前一个点超速了且后一个点没超速
					       currCarHistory.getGpsSpeed() < overSpeedValueCurr) {
					if (overSpeed.getTotal() > Constant.overSpeedDoubtTotal) {
						if (overSpeed.getAutoAnalysisdata() != null && overSpeed.getStartHistory() != null) {
							//如果超速了一次就增加一次ecu异常可疑数
							EcuException ecuException = carAnalysis.getEcuException();
							ecuException.setEcuExceptionDoubtTotal(ecuException.getEcuExceptionDoubtTotal() + 1);
							ecuException.setLastUpdateTime(new DateTime(currCarHistory.getReceiveTime()));
							
							AutoAnalysisdata autoAnalysisdata = overSpeed.getAutoAnalysisdata();
							autoAnalysisdata.setEventType(Constant.overSpeedType);
							autoAnalysisdata.setGpsPosX(overSpeed.getStartHistory().getGeo().getX());
							autoAnalysisdata.setGpsPosY(overSpeed.getStartHistory().getGeo().getY());
							autoAnalysisdata.setGpsSpeed(overSpeed.getStartHistory().getGpsSpeed());
							autoAnalysisdata.setGpsHeight(overSpeed.getStartHistory().getGpsHeight());
							autoAnalysisdata.setBoxUp(overSpeed.getStartHistory().getBoxUp());
							autoAnalysisdata.setBoxEmpty(overSpeed.getStartHistory().getBoxEmpty());
							autoAnalysisdata.setBoxClose(overSpeed.getStartHistory().getBoxClose());
							autoAnalysisdata.setInsertTime(new Date());
							Date vioStarttime = new Date(overSpeed.getStartHistory().getReceiveTime());
							Date vioEndtime = new Date(currCarHistory.getReceiveTime());
							autoAnalysisdata.setVioStarttime(vioStarttime);
							autoAnalysisdata.setVioEndtime(vioEndtime);
							Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
							autoAnalysisdata.setViolationsTime(violationsTime);
							if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getGpsSpeed()) {
								autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
							}
							Iterator<Map.Entry<Long, List<Point>>> districtIt = FenceConstant.districtMap.entrySet().iterator();  
					        while (districtIt.hasNext()) {
					        	Map.Entry<Long, List<Point>> entry = districtIt.next();
					        	if (GeoUtil.containsPoint(entry.getValue(), new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY()))) {
					        		autoAnalysisdata.setDistrictId(entry.getKey());
					        		break;
					        	}
					        }
					        autoAnalysisdata.setRemark("");
					        CloseableHttpResponse httpResponseStart = null;
					        CloseableHttpResponse httpResponseEnd = null;
							try {
								CloseableHttpClient httpclient = HttpClients.createDefault();
							    RequestConfig requestConfig = RequestConfig.custom()
							    		.setSocketTimeout(5000)  
							            .setConnectTimeout(5000)  
							            .setConnectionRequestTimeout(5000)
							            .build();
								URI uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
								        .build();
								HttpGet httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseStart = httpclient.execute(httpget);
								ObjectMapper objectMapper = new ObjectMapper();
					    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							
					    		uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
								        .build();
								httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseEnd = httpclient.execute(httpget);
								objectMapper = new ObjectMapper();
					    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							} catch (URISyntaxException | IOException e) {
								logger.error("", e);
								e.printStackTrace();
							} finally {
								if (httpResponseStart != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
								if (httpResponseEnd != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
							}
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
						}
					}
					overSpeed.setAutoAnalysisdata(null);
					overSpeed.setStartHistory(null);
					overSpeed.setTotal(0);
				} else {
					overSpeed.setAutoAnalysisdata(null);
					overSpeed.setStartHistory(null);
					overSpeed.setTotal(0);
				}
			}
		}
	}
	
	//有位移无速度分析
	@Transactional(propagation = Propagation.NEVER)
	public void moveAndNoSpeedAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		MoveAndNoSpeed  moveAndNoSpeed = carAnalysis.getMoveAndNoSpeed();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			
			if (prevCarHistory != null && currCarHistory != null) {
				Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
				Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
				Double distance = GeoUtil.getDistance(p1, p2);
				// 如果两点之间位移超过了临界值且速度超过了临界值
				if (distance > Constant.moveAndSpeedDistance && distance < 1000 &&
					currCarHistory.getGpsSpeed() < Constant.moveAndSpeedValue &&
					moveAndNoSpeed.getTotal() == 0) {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
					moveAndNoSpeed.setAutoAnalysisdata(autoAnalysisdata);
					moveAndNoSpeed.setStartHistory(currCarHistory);
					moveAndNoSpeed.setTotal(1);
				} else if (distance > Constant.moveAndSpeedDistance && distance < 1000 && // 如果是位移超过了临界值且速度超过了临界值且连续超速点大于0
						   currCarHistory.getGpsSpeed() < Constant.moveAndSpeedValue &&
						   moveAndNoSpeed.getTotal() > 0) {
					if (moveAndNoSpeed.getAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = moveAndNoSpeed.getAutoAnalysisdata();
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + distance.intValue());
						if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					moveAndNoSpeed.setTotal(moveAndNoSpeed.getTotal() + 1);
				} else {
					// 如果超速连续超过了临界点数则记为一次超速
					if (moveAndNoSpeed.getTotal() > Constant.moveAndSpeedDoubtTotal && 
						moveAndNoSpeed.getAutoAnalysisdata() != null && 
						moveAndNoSpeed.getStartHistory() != null) {
						AutoAnalysisdata autoAnalysisdata = moveAndNoSpeed.getAutoAnalysisdata();
						autoAnalysisdata.setEventType(Constant.moveAndNoSpeedType);
						autoAnalysisdata.setGpsPosX(moveAndNoSpeed.getStartHistory().getGeo().getX());
						autoAnalysisdata.setGpsPosY(moveAndNoSpeed.getStartHistory().getGeo().getY());
						autoAnalysisdata.setGpsSpeed(moveAndNoSpeed.getStartHistory().getGpsSpeed());
						autoAnalysisdata.setGpsHeight(moveAndNoSpeed.getStartHistory().getGpsHeight());
						autoAnalysisdata.setBoxUp(moveAndNoSpeed.getStartHistory().getBoxUp());
						autoAnalysisdata.setBoxEmpty(moveAndNoSpeed.getStartHistory().getBoxEmpty());
						autoAnalysisdata.setBoxClose(moveAndNoSpeed.getStartHistory().getBoxClose());
						autoAnalysisdata.setInsertTime(new Date());
						Date vioStarttime = new Date(moveAndNoSpeed.getStartHistory().getReceiveTime());
						Date vioEndtime = new Date(currCarHistory.getReceiveTime());
						autoAnalysisdata.setVioStarttime(vioStarttime);
						autoAnalysisdata.setVioEndtime(vioEndtime);
						Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
						autoAnalysisdata.setViolationsTime(violationsTime);
						autoAnalysisdata.setRemark("");
				        CloseableHttpResponse httpResponseStart = null;
				        CloseableHttpResponse httpResponseEnd = null;
						try {
							CloseableHttpClient httpclient = HttpClients.createDefault();
						    RequestConfig requestConfig = RequestConfig.custom()
						    		.setSocketTimeout(5000)  
						            .setConnectTimeout(5000)  
						            .setConnectionRequestTimeout(5000)
						            .build();
							URI uri = new URIBuilder()
							        .setScheme("http")
							        .setHost("api.map.baidu.com")
							        .setPath("/geocoder/v2/")
							        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
							        .setParameter("output", "json")
							        .setParameter("pois", "1")
							        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
							        .build();
							HttpGet httpget = new HttpGet(uri);
							httpget.setConfig(requestConfig);
							httpResponseStart = httpclient.execute(httpget);
							ObjectMapper objectMapper = new ObjectMapper();
				    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
				    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
						
				    		uri = new URIBuilder()
							        .setScheme("http")
							        .setHost("api.map.baidu.com")
							        .setPath("/geocoder/v2/")
							        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
							        .setParameter("output", "json")
							        .setParameter("pois", "1")
							        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
							        .build();
							httpget = new HttpGet(uri);
							httpget.setConfig(requestConfig);
							httpResponseEnd = httpclient.execute(httpget);
							objectMapper = new ObjectMapper();
				    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
				    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
						} catch (URISyntaxException | IOException e) {
							logger.error("", e);
							e.printStackTrace();
						} finally {
							if (httpResponseStart != null) {
								try {
									httpResponseStart.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
							if (httpResponseEnd != null) {
								try {
									httpResponseStart.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
						autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
					}
					moveAndNoSpeed.setAutoAnalysisdata(null);
					moveAndNoSpeed.setStartHistory(null);
					moveAndNoSpeed.setTotal(0);
				}
			}
		}
	}
	
	//有速度无位移分析
	@Transactional(propagation = Propagation.NEVER)
	public void speedAndNoMoveAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		SpeedAndNoMove  speedAndNoMove = carAnalysis.getSpeedAndNoMove();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			
			if (prevCarHistory != null && currCarHistory != null) {
				Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
				Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
				Double distance = GeoUtil.getDistance(p1, p2);
				
				if (prevCarHistory.getGpsSpeed() <= Constant.speedAndMoveValue && // 如果前一个点速度小于临界值，后一个点大于临界值，且位移小于临界值
					currCarHistory.getGpsSpeed() >= Constant.speedAndMoveValue &&
					distance < Constant.speedAndMoveDistance && 
					speedAndNoMove.getTotal() == 0) {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
					speedAndNoMove.setAutoAnalysisdata(autoAnalysisdata);
					speedAndNoMove.setStartHistory(currCarHistory);
					speedAndNoMove.setTotal(1);
				} else if (prevCarHistory.getGpsSpeed() >= Constant.speedAndMoveValue && // 如果前一个点速度大于临界值，后一个点大于临界值，且位移小于临界值则是连续的可疑点
						   currCarHistory.getGpsSpeed() >= Constant.speedAndMoveValue &&
						   distance < Constant.speedAndMoveDistance && 
						   speedAndNoMove.getTotal() > 0) {
					if (speedAndNoMove.getAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = speedAndNoMove.getAutoAnalysisdata();
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + distance.intValue());
						if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					speedAndNoMove.setTotal(speedAndNoMove.getTotal() + 1);
				} else {
					if (speedAndNoMove.getTotal() > Constant.speedAndMoveDoubtTotal && // 如果可疑点数量大于临界值则新增一条违规记录
						speedAndNoMove.getAutoAnalysisdata() != null && 
						speedAndNoMove.getStartHistory() != null) {
						AutoAnalysisdata autoAnalysisdata = speedAndNoMove.getAutoAnalysisdata();
						autoAnalysisdata.setEventType(Constant.speedAndNoMoveType);
						autoAnalysisdata.setGpsPosX(speedAndNoMove.getStartHistory().getGeo().getX());
						autoAnalysisdata.setGpsPosY(speedAndNoMove.getStartHistory().getGeo().getY());
						autoAnalysisdata.setGpsSpeed(speedAndNoMove.getStartHistory().getGpsSpeed());
						autoAnalysisdata.setGpsHeight(speedAndNoMove.getStartHistory().getGpsHeight());
						autoAnalysisdata.setBoxUp(speedAndNoMove.getStartHistory().getBoxUp());
						autoAnalysisdata.setBoxEmpty(speedAndNoMove.getStartHistory().getBoxEmpty());
						autoAnalysisdata.setBoxClose(speedAndNoMove.getStartHistory().getBoxClose());
						autoAnalysisdata.setInsertTime(new Date());
						Date vioStarttime = new Date(speedAndNoMove.getStartHistory().getReceiveTime());
						Date vioEndtime = new Date(currCarHistory.getReceiveTime());
						autoAnalysisdata.setVioStarttime(vioStarttime);
						autoAnalysisdata.setVioEndtime(vioEndtime);
						Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
						autoAnalysisdata.setViolationsTime(violationsTime);
						autoAnalysisdata.setRemark("");
				        CloseableHttpResponse httpResponseStart = null;
				        CloseableHttpResponse httpResponseEnd = null;
						try {
							CloseableHttpClient httpclient = HttpClients.createDefault();
						    RequestConfig requestConfig = RequestConfig.custom()
						    		.setSocketTimeout(5000)  
						            .setConnectTimeout(5000)  
						            .setConnectionRequestTimeout(5000)
						            .build();
							URI uri = new URIBuilder()
							        .setScheme("http")
							        .setHost("api.map.baidu.com")
							        .setPath("/geocoder/v2/")
							        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
							        .setParameter("output", "json")
							        .setParameter("pois", "1")
							        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
							        .build();
							HttpGet httpget = new HttpGet(uri);
							httpget.setConfig(requestConfig);
							httpResponseStart = httpclient.execute(httpget);
							ObjectMapper objectMapper = new ObjectMapper();
				    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
				    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
						
				    		uri = new URIBuilder()
							        .setScheme("http")
							        .setHost("api.map.baidu.com")
							        .setPath("/geocoder/v2/")
							        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
							        .setParameter("output", "json")
							        .setParameter("pois", "1")
							        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
							        .build();
							httpget = new HttpGet(uri);
							httpget.setConfig(requestConfig);
							httpResponseEnd = httpclient.execute(httpget);
							objectMapper = new ObjectMapper();
				    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
				    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
						} catch (URISyntaxException | IOException e) {
							logger.error("", e);
							e.printStackTrace();
						} finally {
							if (httpResponseStart != null) {
								try {
									httpResponseStart.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
							if (httpResponseEnd != null) {
								try {
									httpResponseStart.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
						autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
					}
					speedAndNoMove.setAutoAnalysisdata(null);
					speedAndNoMove.setStartHistory(null);
					speedAndNoMove.setTotal(0);
				}
			}
		}
	}
	
	//闯禁分析
	@Transactional(propagation = Propagation.NEVER)
	public void inRestrictAreaAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		InRestrictArea  inRestrictArea = carAnalysis.getInRestrictArea();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			
			if (prevCarHistory != null && currCarHistory != null) {
				for (List<Point> polygon: accessData.getFenceConstant().getRestrictMap().values()) {
					Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
					Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
					if (GeoUtil.containsPoint(polygon, p1) && GeoUtil.containsPoint(polygon, p2)) { // 如果连续的2个点都在禁区内
						if (inRestrictArea.getAutoAnalysisdata() != null) {
							AutoAnalysisdata autoAnalysisdata = inRestrictArea.getAutoAnalysisdata();
							autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + GeoUtil.getDistance(p1, p2).intValue());
							if (autoAnalysisdata.getGpsSpeed() == null) {
								autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
							} else if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
								autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
							}
						}
						inRestrictArea.setTotal(inRestrictArea.getTotal() + 1);
					} else if (!GeoUtil.containsPoint(polygon, p1) && GeoUtil.containsPoint(polygon, p2)) { // 如果前一个点不在禁区后一个点在禁区则是进入了禁区
						AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
						autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
						autoAnalysisdata.setViolationsMileage(0);
						inRestrictArea.setAutoAnalysisdata(autoAnalysisdata);
						inRestrictArea.setStartHistory(currCarHistory);
						Iterator<Map.Entry<Long, List<Point>>> districtIt = FenceConstant.districtMap.entrySet().iterator();  
				        while (districtIt.hasNext()) {
				        	Map.Entry<Long, List<Point>> entry = districtIt.next();
				        	if (GeoUtil.containsPoint(entry.getValue(), new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY()))) {
				        		autoAnalysisdata.setDistrictId(entry.getKey());
				        		break;
				        	}
				        }
						inRestrictArea.setTotal(1);
					} else if (GeoUtil.containsPoint(polygon, p1) && !GeoUtil.containsPoint(polygon, p2)) { // 如果前一个点在禁区后一个点不在禁区则是离开了禁区
						if (inRestrictArea.getAutoAnalysisdata() != null && inRestrictArea.getStartHistory() != null) {
							if (inRestrictArea.getTotal() > Constant.inRestrictAreaDoubtTotal) { // 疑似闯禁次数大于临界数则记为一次违规
								AutoAnalysisdata autoAnalysisdata = inRestrictArea.getAutoAnalysisdata();
								autoAnalysisdata.setEventType(Constant.inRestrictAreaType);
								autoAnalysisdata.setGpsPosX(inRestrictArea.getStartHistory().getGeo().getX());
								autoAnalysisdata.setGpsPosY(inRestrictArea.getStartHistory().getGeo().getY());
								autoAnalysisdata.setGpsSpeed(inRestrictArea.getStartHistory().getGpsSpeed());
								autoAnalysisdata.setGpsHeight(inRestrictArea.getStartHistory().getGpsHeight());
								autoAnalysisdata.setBoxUp(inRestrictArea.getStartHistory().getBoxUp());
								autoAnalysisdata.setBoxEmpty(inRestrictArea.getStartHistory().getBoxEmpty());
								autoAnalysisdata.setBoxClose(inRestrictArea.getStartHistory().getBoxClose());
								autoAnalysisdata.setInsertTime(new Date());
								Date vioStarttime = new Date(inRestrictArea.getStartHistory().getReceiveTime());
								Date vioEndtime = new Date(currCarHistory.getReceiveTime());
								autoAnalysisdata.setVioStarttime(vioStarttime);
								autoAnalysisdata.setVioEndtime(vioEndtime);
								Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
								autoAnalysisdata.setViolationsTime(violationsTime);
								autoAnalysisdata.setRemark("");
						        CloseableHttpResponse httpResponseStart = null;
						        CloseableHttpResponse httpResponseEnd = null;
								try {
									CloseableHttpClient httpclient = HttpClients.createDefault();
								    RequestConfig requestConfig = RequestConfig.custom()
								    		.setSocketTimeout(5000)  
								            .setConnectTimeout(5000)  
								            .setConnectionRequestTimeout(5000)
								            .build();
									URI uri = new URIBuilder()
									        .setScheme("http")
									        .setHost("api.map.baidu.com")
									        .setPath("/geocoder/v2/")
									        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
									        .setParameter("output", "json")
									        .setParameter("pois", "1")
									        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
									        .build();
									HttpGet httpget = new HttpGet(uri);
									httpget.setConfig(requestConfig);
									httpResponseStart = httpclient.execute(httpget);
									ObjectMapper objectMapper = new ObjectMapper();
						    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
						    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
								
						    		uri = new URIBuilder()
									        .setScheme("http")
									        .setHost("api.map.baidu.com")
									        .setPath("/geocoder/v2/")
									        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
									        .setParameter("output", "json")
									        .setParameter("pois", "1")
									        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
									        .build();
									httpget = new HttpGet(uri);
									httpget.setConfig(requestConfig);
									httpResponseEnd = httpclient.execute(httpget);
									objectMapper = new ObjectMapper();
						    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
						    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
								} catch (URISyntaxException | IOException e) {
									logger.error("", e);
									e.printStackTrace();
								} finally {
									if (httpResponseStart != null) {
										try {
											httpResponseStart.close();
										} catch (IOException e) {
											e.printStackTrace();
										}
									}
									if (httpResponseEnd != null) {
										try {
											httpResponseStart.close();
										} catch (IOException e) {
											e.printStackTrace();
										}
									}
								}
								autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
							}
						}
						
						//清空疑似数据
						inRestrictArea.setAutoAnalysisdata(null);
						inRestrictArea.setStartHistory(null);
						inRestrictArea.setTotal(0);
					} else {
						inRestrictArea.setAutoAnalysisdata(null);
						inRestrictArea.setStartHistory(null);
						inRestrictArea.setTotal(0);
					}
				}
			}
		}
	}
	
	//非法举斗分析
	@Transactional(propagation = Propagation.NEVER)
	public void illegalBucketAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		IllegalBucket illegalBucket = carAnalysis.getIllegalBucket();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			if (prevCarHistory != null && currCarHistory != null) {
				if (prevCarHistory.getBoxEmpty() == 2 && prevCarHistory.getBoxUp() == 1 &&
						currCarHistory.getBoxUp() == 2 && illegalBucket.getBoxPingFangTotal() > 20) {
					Point currPoint = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
					//判断是否在卸区围栏内
					boolean result = false;
					Iterator<Map.Entry<Long, List<Point>>> it = accessData.getFenceConstant().getUnloadingMap().entrySet().iterator();
		        	while (it.hasNext()) {
		        		Map.Entry<Long, List<Point>> entry = it.next();
		        		if (GeoUtil.containsPoint(entry.getValue(), currPoint)) {
		        			result = true;
		        			break;
		        		}
		        	}
		        	//如果不在卸区围栏内，判断是否在工地围栏内，在工地内举斗属于内转，不算违规卸土
		        	if (result == false) {
			        	it = accessData.getFenceConstant().getConsappMap().entrySet().iterator();
			        	while (it.hasNext()) {
			        		Map.Entry<Long, List<Point>> entry = it.next();
			        		if (GeoUtil.containsPoint(entry.getValue(), currPoint)) {
			        			result = true;
			        			break;
			        		}
			        	}
		        	}
		        	//如果不在卸区和工地围栏内则属于违规卸土
		        	if (result == false) {
		        		AutoAnalysisdata autoAnalysisdata = 
								new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
		        		autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
		        		autoAnalysisdata.setEventType(Constant.illegalBucketType);
						autoAnalysisdata.setGpsPosX(currCarHistory.getGeo().getX());
						autoAnalysisdata.setGpsPosY(currCarHistory.getGeo().getY());
						autoAnalysisdata.setGpsSpeed(currCarHistory.getGpsSpeed());
						autoAnalysisdata.setGpsHeight(0F);
						autoAnalysisdata.setBoxUp((byte) 2);
						autoAnalysisdata.setBoxEmpty((byte) 0);
						autoAnalysisdata.setBoxClose((byte) 0);
						autoAnalysisdata.setInsertTime(new Date());
						autoAnalysisdata.setVioStarttime(new Date(currCarHistory.getReceiveTime()));
						CloseableHttpResponse httpResponse = null;
						try {
							CloseableHttpClient httpclient = HttpClients.createDefault();
						    RequestConfig requestConfig = RequestConfig.custom()
						    		.setSocketTimeout(5000)  
						            .setConnectTimeout(5000)  
						            .setConnectionRequestTimeout(5000)
						            .build();
							URI uri = new URIBuilder()
							        .setScheme("http")
							        .setHost("api.map.baidu.com")
							        .setPath("/geocoder/v2/")
							        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
							        .setParameter("output", "json")
							        .setParameter("pois", "1")
							        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
							        .build();
							HttpGet httpget = new HttpGet(uri);
							httpget.setConfig(requestConfig);
							httpResponse = httpclient.execute(httpget);
							ObjectMapper objectMapper = new ObjectMapper();
				    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponse.getEntity()), HashMap.class);
				    		autoAnalysisdata.setRemark("举斗地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
						} catch (URISyntaxException | IOException e) {
							logger.error("", e);
							e.printStackTrace();
						} finally {
							if (httpResponse != null) {
								try {
									httpResponse.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
						autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
		        	}
				}
				if (prevCarHistory.getBoxUp() == 1 && currCarHistory.getBoxUp() == 1) {
					illegalBucket.setBoxPingFangTotal(illegalBucket.getBoxPingFangTotal() + 1);
				}
				if (currCarHistory.getBoxUp() == 2) {
					illegalBucket.setBoxPingFangTotal(0);
				}
			}
		}
		
	}
	
	//偷运分析
	/*@Transactional(propagation = Propagation.NEVER)
	public void smuggleAnalysis(CarAnalysis carAnalysis) {
		
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		Smuggle smuggle = carAnalysis.getSmuggle();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		
		CarHistory prevCarHistory = null;
		CarHistory nextCarHistory = null;
		for (int i = 0; i < carHistorys.size(); i++) {
			if (i == 0) {
				if (lastCarHistory != null) {
					prevCarHistory = lastCarHistory;
					nextCarHistory = carHistorys.get(0);
				}
			} else {
				prevCarHistory = carHistorys.get(i - 1);
				nextCarHistory = carHistorys.get(i);
			}
			if (prevCarHistory != null && nextCarHistory != null) {
				if (prevCarHistory.getBoxEmpty() == 1 && nextCarHistory.getBoxEmpty() == 2) {
					boolean cheat = true;
					for (List<Point> polygon: FenceConst.consappMap.values()) {
						Point point1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
						Point point2 = new Point(nextCarHistory.getGeo().getX(), nextCarHistory.getGeo().getY());
						if (GeoUtil.containsPoint(polygon, point1) || GeoUtil.containsPoint(polygon, point2)) {
							cheat = false;
							break;
						}
					}
					//如果距离围栏边界点1000米范围内也行
					if (cheat == true) {
						for (List<Point> polygon: FenceConst.consappMap.values()) {
							for (Point point: polygon) {
								if (GeoUtil.getDistance(new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY()), point) <= 1000) {
									cheat = false;
									break;
								}
							}
						}
					}
					if (cheat) {
						smuggle.setStart(prevCarHistory);
						AutoAnalysisdata autoAnalysisdata = 
								new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
						autoAnalysisdata.setEventType(Constant.smuggleType);
						autoAnalysisdata.setGpsPosX(prevCarHistory.getGeo().getX());
						autoAnalysisdata.setGpsPosY(prevCarHistory.getGeo().getY());
						autoAnalysisdata.setGpsSpeed(prevCarHistory.getGpsSpeed());
						autoAnalysisdata.setGpsHeight(prevCarHistory.getGpsHeight());
						autoAnalysisdata.setBoxUp(prevCarHistory.getBoxUp());
						autoAnalysisdata.setBoxEmpty(prevCarHistory.getBoxEmpty());
						autoAnalysisdata.setBoxClose(prevCarHistory.getBoxClose());
						autoAnalysisdata.setInsertTime(new Date());
						autoAnalysisdata.setVioStarttime(new Date(prevCarHistory.getReceiveTime()));
						smuggle.setAutoAnalysisdata(autoAnalysisdata);
					}
				} else if ((prevCarHistory.getBoxEmpty() == 2 && nextCarHistory.getBoxEmpty() == 1) ) {
					if (smuggle.getStart() != null && smuggle.getAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = smuggle.getAutoAnalysisdata();
						Date endTime = new Date(nextCarHistory.getReceiveTime());
						autoAnalysisdata.setVioEndtime(endTime);
						Integer violationsTime = Seconds.secondsBetween(new DateTime(new Date(smuggle.getStart().getReceiveTime())), new DateTime(new Date(nextCarHistory.getReceiveTime()))).getSeconds();
						autoAnalysisdata.setViolationsTime(violationsTime);
						Point point1 = new Point(smuggle.getStart().getGeo().getX(), smuggle.getStart().getGeo().getY());
						Point point2 = new Point(nextCarHistory.getGeo().getX(), nextCarHistory.getGeo().getY());
						Double violationsMileage = GeoUtil.getDistance(point1, point2);
						autoAnalysisdata.setViolationsMileage(violationsMileage.intValue());
						if (violationsMileage > 300 && violationsTime > 1000) {
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
						}
						smuggle.setStart(null);
						smuggle.setEnd(null);
						smuggle.setAutoAnalysisdata(null);
					}
				}
			}
		}
		if (smuggle.getStart() != null && new DateTime(smuggle.getStart().getReceiveTime()).plusHours(3).isBeforeNow()) {
			smuggle.setStart(null);
			smuggle.setEnd(null);
			smuggle.setAutoAnalysisdata(null);
		}
	}*/
	
	//违规开停工分析
	@Transactional(propagation = Propagation.NEVER)
	public void illegalWorkAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		IllegalWork illegalWork = carAnalysis.getIllegalWork();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		LocalTime nowTime = LocalTime.now();
		
		//开始分析提前开工
		LocalTime consappStartTime = LocalTime.parse("18:15:00", DateTimeFormat.forPattern("HH:mm:ss"));
		LocalTime consappEndTime = LocalTime.parse("22:15:00", DateTimeFormat.forPattern("HH:mm:ss"));
		//如果时间在:15:00和22:15:00之间才开始计算提前开工
		if (nowTime.isAfter(consappStartTime) && nowTime.isBefore(consappEndTime)) {
			for (int i = 0; i < carHistorys.size(); i++) {
				CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
				CarHistory currCarHistory = carHistorys.get(i);
				if (prevCarHistory != null && currCarHistory != null) {
					Point prevPoint = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
		        	Point currPoint = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
					List<Long> consappFenceIds = accessData.getCardConstant().getCarConsappMap().get(carAnalysis.getCarNumber());
		        	
					Map<Long, List<Point>> consappPolygons = new HashMap<Long, List<Point>>();
		        	if (consappFenceIds != null) {
		        		for (Long consappFenceId: consappFenceIds) {
		        			if (accessData.getFenceConstant().getConsappMap().get(consappFenceId) != null) {
		        				consappPolygons.put(consappFenceId, accessData.getFenceConstant().getConsappMap().get(consappFenceId));
		        			}
		        		}
		        	}
		        	Iterator<Entry<Long, List<Point>>> consappIt= consappPolygons.entrySet().iterator();
		        	while (consappIt.hasNext()) {
		        		Entry<Long, List<Point>> entry = consappIt.next();
		        		Long key = entry.getKey();
		        		List<Point> consappPolygon = entry.getValue();
			        	//如果前一个点不在工地和当前点在工地内则将违规开停工分析对象设置值
			        	if (!GeoUtil.containsPoint(consappPolygon, prevPoint) &&
			        		GeoUtil.containsPoint(consappPolygon, currPoint)) {
			        		illegalWork.setInConsappTotal(1);
			        		break;
			            } else if (GeoUtil.containsPoint(consappPolygon, prevPoint) && //如果前一个点和当前点都在工地且速度小于20km/h
			        		       GeoUtil.containsPoint(consappPolygon, currPoint) &&
			        		       currCarHistory.getGpsSpeed() < 20) {
			            	illegalWork.setInConsappTotal(illegalWork.getInConsappTotal() + 1);
			            	if (illegalWork.getInConsappMap().get(key) != null) {
			            		illegalWork.getInConsappMap().put(key, illegalWork.getInConsappMap().get(key) + 1);
			            	} else {
			            		illegalWork.getInConsappMap().put(key, 1);
			            	}
			            } else if (GeoUtil.containsPoint(consappPolygon, prevPoint) && //如果前一个点在工地而当前点不在工地
		        		           !GeoUtil.containsPoint(consappPolygon, currPoint)) {
			            	illegalWork.setLeaveConsappHistory(currCarHistory);
			            	illegalWork.setOutConsappTotal(1);
			            } else if (illegalWork.getLeaveConsappHistory() != null && //离开工地时的轨迹点不为空且前一个点和当前点都不在工地且距离工地的最小距离大于2000米
			            		   !GeoUtil.containsPoint(consappPolygon, prevPoint) &&
	        		               !GeoUtil.containsPoint(consappPolygon, currPoint) && 
	        		               GeoUtil.getMinDistance(currPoint, consappPolygon) > 2000) {
			            	//如果前一个点和当前点的速度都小于20km每小时则是在原地等待出工地
			            	if (GeoUtil.getMinDistance(prevPoint, consappPolygon) < 200 &&
				            	GeoUtil.getMinDistance(currPoint, consappPolygon) < 200 &&
				            	GeoUtil.getDistance(prevPoint, currPoint) < 30) {
			            		illegalWork.setWaitConsappTotal(illegalWork.getWaitConsappTotal() + 1);
			            		illegalWork.setOutConsappTotal(1);
			            	} else {
			            		illegalWork.setOutConsappTotal(illegalWork.getOutConsappTotal() + 1);
			            	}
			            	if (illegalWork.getWaitConsappTotal() > 6) {
			            		illegalWork.setLeaveConsappHistory(currCarHistory);
			            	}
			            }
			        }
			        
			        //如果在工地里面的次数达到十次且离开工地时间不为空且在工地外面的次数达到10次，且开工时间不在工作时间内则是提前开工
			        if (illegalWork.getInConsappTotal() >= 10 && illegalWork.getLeaveConsappHistory() != null &&
			        	illegalWork.getOutConsappTotal() >= 10) {
			        	Iterator<Entry<Long, Integer>> allMap = illegalWork.getInConsappMap().entrySet().iterator();
			        	Long consappFenceid = null;
			        	Integer number = 0;
			        	while (allMap.hasNext()) {
			        		Entry<Long, Integer> entry = allMap.next();
		        			if (entry.getValue() > number) {
		        				number = entry.getValue();
		        				consappFenceid = entry.getKey();
		        			}
			        	}
			        	
			        	Integer earlyWorkTime = null;
			        	if (accessData.getCardConstant().getEarlyWorkMap().get(carAnalysis.getCarNumber() + consappFenceid) != null) {
			        		earlyWorkTime = accessData.getCardConstant().getEarlyWorkMap().get(carAnalysis.getCarNumber() + consappFenceid);
			        	}
			        	if (earlyWorkTime != null) {
				        	CarHistory carHistory = illegalWork.getLeaveConsappHistory();
				        	if (carHistory != null && new DateTime(carHistory.getReceiveTime()).getHourOfDay() >= 9 &&
				        		new DateTime(carHistory.getReceiveTime()).getHourOfDay() <= earlyWorkTime) {
				        		AutoAnalysisdata autoAnalysisdata = 
										new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
				        		autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
				        		autoAnalysisdata.setEventType(Constant.illegalWorkType);
								autoAnalysisdata.setGpsPosX(carHistory.getGeo().getX());
								autoAnalysisdata.setGpsPosY(carHistory.getGeo().getY());
								autoAnalysisdata.setGpsSpeed(carHistory.getGpsSpeed());
								autoAnalysisdata.setGpsHeight(0F);
								autoAnalysisdata.setBoxUp((byte) 0);
								autoAnalysisdata.setBoxEmpty((byte) 0);
								autoAnalysisdata.setBoxClose((byte) 0);
								autoAnalysisdata.setInsertTime(new Date());
								autoAnalysisdata.setVioStarttime(new Date(carHistory.getReceiveTime()));
								if (consappFenceid != null) {
									Gpsfence consappFence = gpsfenceMapper.selectByPrimaryKey(consappFenceid);
									if (consappFence.getGuidFence() != null &&
										!"".equals(consappFence.getGuidFence())) {
										Consapp example = new Consapp();
										example.setGongGuidFence(consappFence.getGuidFence());
										List<Consapp> consapps = consappMapper.select(example);
										if (consapps.size() > 0) {
											autoAnalysisdata.setDistrictId(consapps.get(0).getProBelong());
										}
									}
								}
								autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
				        	}
			        	}
			        	
			        	illegalWork.setInConsappTotal(0);
			        	illegalWork.setLeaveConsappHistory(null);
			        	illegalWork.setOutConsappTotal(0);
			        	illegalWork.setWaitConsappTotal(0);
			        	illegalWork.getInConsappMap().clear();
			        }
				}
			}
		}
		
		//开始分析延迟停工
		LocalTime unloadingAreaStartTime = LocalTime.parse("04:15:00", DateTimeFormat.forPattern("HH:mm:ss"));
		LocalTime unloadingAreaEndTime = LocalTime.parse("06:15:00", DateTimeFormat.forPattern("HH:mm:ss"));
		//如果时间在:04:15:00和06:15:00之间才开始计算提前开工
		if (nowTime.isAfter(unloadingAreaStartTime) && nowTime.isBefore(unloadingAreaEndTime)) {
			for (int i = 0; i < carHistorys.size(); i++) {
				CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
				CarHistory currCarHistory = carHistorys.get(i);
				if (prevCarHistory != null && currCarHistory != null) {
					Point prevPoint = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
		        	Point currPoint = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
		        	List<Long> unloadingFenceIds = accessData.getCardConstant().getCarUnloadingMap().get(carAnalysis.getCarNumber());
		        	
		        	// 将消纳场id和围栏数据放入Map供后面计算用
					Map<Long, List<Point>> unloadingPolygons = new HashMap<Long, List<Point>>();
		        	if (unloadingFenceIds != null) {
		        		for (Long unloadingFenceId: unloadingFenceIds) {
		        			if (accessData.getFenceConstant().getUnloadingMap().get(unloadingFenceId) != null) {
		        				unloadingPolygons.put(unloadingFenceId, accessData.getFenceConstant().getUnloadingMap().get(unloadingFenceId));
		        			}
		        		}
		        	}
		        	Iterator<Entry<Long, List<Point>>> unloadingIt = unloadingPolygons.entrySet().iterator();
		        	while (unloadingIt.hasNext()) {
		        		Entry<Long, List<Point>> entry = unloadingIt.next();
		        		Long key = entry.getKey();
		        		List<Point> unloadingPolygon = entry.getValue();
		        		
		        		//如果前一个点不在卸区和当前点在卸区内则将违规开停工分析对象设置值
			        	if (!GeoUtil.containsPoint(unloadingPolygon, prevPoint) &&
			        		GeoUtil.containsPoint(unloadingPolygon, currPoint)) {
			        		illegalWork.setInUnloadingAreaTotal(1);
			        		break;
			            } else if (GeoUtil.containsPoint(unloadingPolygon, prevPoint) && //如果前一个点和当前点都在卸区且速度小于20km/h
			        		       GeoUtil.containsPoint(unloadingPolygon, currPoint) &&
			        		       currCarHistory.getGpsSpeed() < 20) {
			            	illegalWork.setInUnloadingAreaTotal(illegalWork.getInUnloadingAreaTotal() + 1);
			            	if (illegalWork.getInUnloadingMap().get(key) != null) {
			            		illegalWork.getInUnloadingMap().put(key, illegalWork.getInUnloadingMap().get(key) + 1);
			            	} else {
			            		illegalWork.getInUnloadingMap().put(key, 1);
			            	}
			            } else if (GeoUtil.containsPoint(unloadingPolygon, prevPoint) && //如果前一个点在卸区而当前点不在卸区
		        		           !GeoUtil.containsPoint(unloadingPolygon, currPoint)) {
			            	illegalWork.setLeaveUnloadingAreaHistory(currCarHistory);
			            	illegalWork.setOutUnloadingAreaTotal(1);
			            } else if (illegalWork.getLeaveUnloadingAreaHistory() != null && //离开卸区时的轨迹点不为空且前一个点和当前点都不在卸区
			            		   !GeoUtil.containsPoint(unloadingPolygon, prevPoint) &&
	        		               !GeoUtil.containsPoint(unloadingPolygon, currPoint) &&
	        		               GeoUtil.getMinDistance(currPoint, unloadingPolygon) > 2000) {
			            	//如果前一个点和当前点的速度都小于20km每小时则是在原地等待出工地
			            	if (GeoUtil.getMinDistance(prevPoint, unloadingPolygon) < 200 &&
				            	GeoUtil.getMinDistance(currPoint, unloadingPolygon) < 200 &&
				            	GeoUtil.getDistance(prevPoint, currPoint) < 30) {
			            		illegalWork.setWaitUnloadingAreaTotal(illegalWork.getWaitUnloadingAreaTotal() + 1);
			            		illegalWork.setOutUnloadingAreaTotal(1);
			            	} else {
			            		illegalWork.setOutUnloadingAreaTotal(illegalWork.getOutUnloadingAreaTotal() + 1);
			            	}
			            	if (illegalWork.getWaitUnloadingAreaTotal() > 6) {
			            		illegalWork.setLeaveUnloadingAreaHistory(currCarHistory);
			            	}
			            }
		        	}
			        
		        	Iterator<Entry<Long, Integer>> allMap = illegalWork.getInUnloadingMap().entrySet().iterator();
		        	Long unloadingFenceid = null;
		        	Integer number = 0;
		        	while (allMap.hasNext()) {
		        		Entry<Long, Integer> entry = allMap.next();
	        			if (entry.getValue() > number) {
	        				number = entry.getValue();
	        				unloadingFenceid = entry.getKey();
	        			}
		        	}
		        	
		        	Integer latestWorkTime = null;
		        	if (accessData.getCardConstant().getLatestWorkMap().get(carAnalysis.getCarNumber() + unloadingFenceid) != null) {
		        		latestWorkTime = accessData.getCardConstant().getLatestWorkMap().get(carAnalysis.getCarNumber() + unloadingFenceid);
		        	}
			        //如果在卸区里面的次数达到十次且离开工地时间不为空且在卸区外面的次数达到10次，且开工时间不在工作时间内则是延迟停工
			        if (latestWorkTime != null && illegalWork.getInUnloadingAreaTotal() >= 10 && 
			        	illegalWork.getLeaveUnloadingAreaHistory() != null &&
			        	illegalWork.getOutUnloadingAreaTotal() >= 10) {
			        	CarHistory carHistory = illegalWork.getLeaveUnloadingAreaHistory();
			        	if (carHistory != null && new DateTime(carHistory.getReceiveTime()).getHourOfDay() > latestWorkTime &&
			        		new DateTime(carHistory.getReceiveTime()).getHourOfDay() <= 6) {
			        		AutoAnalysisdata autoAnalysisdata = 
									new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
							autoAnalysisdata.setEventType(Constant.illegalWorkType);
							autoAnalysisdata.setGpsPosX(carHistory.getGeo().getX());
							autoAnalysisdata.setGpsPosY(carHistory.getGeo().getY());
							autoAnalysisdata.setGpsSpeed(carHistory.getGpsSpeed());
							autoAnalysisdata.setGpsHeight(0F);
							autoAnalysisdata.setBoxUp((byte) 0);
							autoAnalysisdata.setBoxEmpty((byte) 0);
							autoAnalysisdata.setBoxClose((byte) 0);
							autoAnalysisdata.setInsertTime(new Date());
							autoAnalysisdata.setVioStarttime(new Date(carHistory.getReceiveTime()));
							if (unloadingFenceid != null) {
								Gpsfence unloadingFence = gpsfenceMapper.selectByPrimaryKey(unloadingFenceid);
								if (unloadingFence.getGuidFence() != null &&
									!"".equals(unloadingFence.getGuidFence())) {
									UnloadingArea example = new UnloadingArea();
									example.setEnclosureId(unloadingFence.getGuidFence());;
									List<UnloadingArea> unloadingAreas = unloadingAreaMapper.select(example);
									if (unloadingAreas.size() > 0) {
										autoAnalysisdata.setDistrictId(Long.parseLong(unloadingAreas.get(0).getDistrictId()));
									}
								}
							}
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
			        	}
			        	illegalWork.setInUnloadingAreaTotal(0);
			        	illegalWork.setLeaveUnloadingAreaHistory(null);
			        	illegalWork.setOutUnloadingAreaTotal(0);
			        	illegalWork.setWaitUnloadingAreaTotal(0);
			        }
				}
			}
		}
	}
	
	//ecu异常分析
	@Transactional(propagation = Propagation.NEVER)
	public void ecuExceptionAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		EcuException ecuException = carAnalysis.getEcuException();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		if (lastCarHistory != null && 
			ecuException.getEcuExceptionDoubtTotal() > Constant.ecuExceptionDoubtTotal) { // 如果ecu异常数大于临界数则记为一次异常
			AutoAnalysisdata autoAnalysisdata = 
					new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
			autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
			autoAnalysisdata.setEventType(Constant.ecuCheatType);
			autoAnalysisdata.setGpsPosX(lastCarHistory.getGeo().getX());
			autoAnalysisdata.setGpsPosY(lastCarHistory.getGeo().getY());
			autoAnalysisdata.setGpsSpeed(lastCarHistory.getGpsSpeed());
			autoAnalysisdata.setGpsHeight(0F);
			autoAnalysisdata.setBoxUp((byte) 0);
			autoAnalysisdata.setBoxEmpty((byte) 0);
			autoAnalysisdata.setBoxClose((byte) 0);
			autoAnalysisdata.setInsertTime(new Date());
			autoAnalysisdata.setVioStarttime(new Date(lastCarHistory.getReceiveTime()));
			autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
			
			//初始化ecu异常可疑数
			ecuException.setEcuExceptionDoubtTotal(0);
		}
		
		//如果超过5天还没有计算出ecu异常则将可疑数置为0
		if (ecuException.getLastUpdateTime().plusDays(5).isBeforeNow()) {
			ecuException.setEcuExceptionDoubtTotal(0);
			ecuException.setLastUpdateTime(null);
		}
	}
	
	//越界分析
	@Transactional(propagation = Propagation.NEVER)
	public void outBoundAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		OutBound outBound = carAnalysis.getOutBound();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		//如果不在工作时间则不开始分析
		if (DateTime.now().getHourOfDay() > 5 && DateTime.now().getHourOfDay() < 18) {
			return;
		}
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			//如果前一个轨迹点和当前轨迹点均不为空才能分析
			if (prevCarHistory != null && currCarHistory != null) {
				Point prevPoint = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
	        	Point currPoint = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
	        	//如果都在三环以内
	        	if (GeoUtil.containsPoint(FenceConstant.secondLoopLine, prevPoint) &&
	        		GeoUtil.containsPoint(FenceConstant.secondLoopLine, currPoint)) {
	        		boolean result = false;
	        		//判断是否在工地内
	        		Iterator<Map.Entry<Long, List<Point>>> it = accessData.getFenceConstant().getConsappMap().entrySet().iterator();  
			        while (it.hasNext()) {
			        	Map.Entry<Long, List<Point>> entry = it.next(); 
			        	if (GeoUtil.containsPoint(entry.getValue(), prevPoint) ||
			        		GeoUtil.containsPoint(entry.getValue(), currPoint)) {
			        		result = true;
			        		break;
			        	}
			        }
			        //判断是否在卸区内
			        if (result == true) {
			        	continue;
			        } else {
			        	it = accessData.getFenceConstant().getUnloadingMap().entrySet().iterator();
			        	while (it.hasNext()) {
				        	Map.Entry<Long, List<Point>> entry = it.next(); 
				        	if (GeoUtil.containsPoint(entry.getValue(), prevPoint) ||
				        		GeoUtil.containsPoint(entry.getValue(), currPoint)) {
				        		result = true;
				        		break;
				        	}
				        }
			        }
			        //判断是否在停车场内
			        if (result == true) {
			        	continue;
			        } else {
			        	it = accessData.getFenceConstant().getParkingMap().entrySet().iterator();
			        	while (it.hasNext()) {
				        	Map.Entry<Long, List<Point>> entry = it.next(); 
				        	if (GeoUtil.containsPoint(entry.getValue(), prevPoint) ||
				        		GeoUtil.containsPoint(entry.getValue(), currPoint)) {
				        		result = true;
				        		break;
				        	}
				        }
			        }
			        //如果都不在工地、卸区、停车场内
			        if (result == false) {
			        	List<Long> lineFenceIds = accessData.getCardConstant().getCarLineMap().get(carAnalysis.getCarNumber());
			        	List<List<Point>> linePolygons = new ArrayList<List<Point>>();
			        	if (lineFenceIds != null) {
			        		for (Long lineFenceId: lineFenceIds) {
			        			if (accessData.getFenceConstant().getLineMap().get(lineFenceId) != null) {
			        				linePolygons.add(accessData.getFenceConstant().getLineMap().get(lineFenceId));
			        			}
			        		}
			        	}
			        	
			        	if (prevCarHistory.getBoxEmpty() == 1 && currCarHistory.getBoxEmpty() == 2) { // 空车状态不用计算越界
			        		outBound.setOutBoundDoubtTotal(0);
		        			outBound.setStartHistory(null);
			        	} else if (prevCarHistory.getBoxEmpty() == 2 && currCarHistory.getBoxEmpty() == 2) { // 重车状态才计算是否越界
			        		boolean inPolygon = false;
				        	for (List<Point> polygon: linePolygons) {
				        		if (GeoUtil.containsPoint(polygon, currPoint)) {
				        			inPolygon = true;
				        			break;
					        	}
				        	}
				        	if (inPolygon == false && currCarHistory.getGpsSpeed() > 20) {
				        		outBound.setOutBoundDoubtTotal(outBound.getOutBoundDoubtTotal() + 1);
			        			outBound.setStartHistory(currCarHistory);
				        	}
			        	} else if (prevCarHistory.getBoxEmpty() == 2 && currCarHistory.getBoxEmpty() == 1) {
			        		if (outBound.getOutBoundDoubtTotal() > 10) { // 如果越界点数大于临界值则记为一次越界
			        			AutoAnalysisdata autoAnalysisdata = 
		        						new AutoAnalysisdata(carAnalysis.getCarNumber(), carAnalysis.getDevPhone());
			        			autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
			        			autoAnalysisdata.setEventType(Constant.outBoundType);
								autoAnalysisdata.setGpsPosX(outBound.getStartHistory().getGeo().getX());
								autoAnalysisdata.setGpsPosY(outBound.getStartHistory().getGeo().getY());
								autoAnalysisdata.setGpsSpeed(outBound.getStartHistory().getGpsSpeed());
								autoAnalysisdata.setGpsHeight(outBound.getStartHistory().getGpsHeight());
								autoAnalysisdata.setBoxUp(outBound.getStartHistory().getBoxUp());
								autoAnalysisdata.setBoxEmpty(outBound.getStartHistory().getBoxEmpty());
								autoAnalysisdata.setBoxClose(outBound.getStartHistory().getBoxClose());
								autoAnalysisdata.setInsertTime(new Date());
								autoAnalysisdata.setVioStarttime(new Date(outBound.getStartHistory().getReceiveTime()));
								autoAnalysisdata.setRemark("");
						        CloseableHttpResponse httpResponseStart = null;
								try {
									CloseableHttpClient httpclient = HttpClients.createDefault();
								    RequestConfig requestConfig = RequestConfig.custom()
								    		.setSocketTimeout(5000)  
								            .setConnectTimeout(5000)  
								            .setConnectionRequestTimeout(5000)
								            .build();
									URI uri = new URIBuilder()
									        .setScheme("http")
									        .setHost("api.map.baidu.com")
									        .setPath("/geocoder/v2/")
									        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
									        .setParameter("output", "json")
									        .setParameter("pois", "1")
									        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
									        .build();
									HttpGet httpget = new HttpGet(uri);
									httpget.setConfig(requestConfig);
									httpResponseStart = httpclient.execute(httpget);
									ObjectMapper objectMapper = new ObjectMapper();
						    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
						    		autoAnalysisdata.setRemark("越界地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
								} catch (URISyntaxException | IOException e) {
									logger.error("", e);
									e.printStackTrace();
								} finally {
									if (httpResponseStart != null) {
										try {
											httpResponseStart.close();
										} catch (IOException e) {
											e.printStackTrace();
										}
									}
								}
			        		}
			        		outBound.setOutBoundDoubtTotal(0);
		        			outBound.setStartHistory(null);
			        	}
			        }
	        	}
			}
		}
	}
	
	//开关箱、重空车、举升数据异常分析
	@Transactional(propagation = Propagation.NEVER)
	public void boxStateAnalysis(AccessData accessData, CarAnalysis carAnalysis) {
		List<CarHistory> carHistorys = carAnalysis.getCarHistoryList();
		BoxState boxState = carAnalysis.getBoxState();
		CarHistory lastCarHistory = carAnalysis.getLastCarHistory();
		Map<String, String> carEnterpriseNameMap = accessData.getCarConstant().getCarEnterpriseNameMap();
		
		//如果8个小时还没分析出来结果就重新计算
		if (boxState.getBoxCloseStartHistory() != null) {
			if (new DateTime(boxState.getBoxCloseStartHistory().getReceiveTime()).plusHours(8).isBefore(DateTime.now())) {
				boxState.setBoxCloseAutoAnalysisdata(null);
				boxState.setBoxCloseStartHistory(null);
				boxState.setBoxCloseTotal(0);
			}
		}
		if (boxState.getBoxEmptyStartHistory() != null) {
			if (new DateTime(boxState.getBoxEmptyStartHistory().getReceiveTime()).plusHours(8).isBefore(DateTime.now())) {
				boxState.setBoxEmptyAutoAnalysisdata(null);
				boxState.setBoxEmptyStartHistory(null);
				boxState.setBoxEmptyTotal(0);
			}
		}
		if (boxState.getBoxUpStartHistory() != null) {
			if (new DateTime(boxState.getBoxUpStartHistory().getReceiveTime()).plusHours(8).isBefore(DateTime.now())) {
				boxState.setBoxUpAutoAnalysisdata(null);
				boxState.setBoxUpStartHistory(null);
				boxState.setBoxUpTotal(0);
			}
		}
		
		for (int i = 0; i < carHistorys.size(); i++) {
			CarHistory prevCarHistory = (i == 0) ? lastCarHistory : carHistorys.get(i - 1);
			CarHistory currCarHistory = carHistorys.get(i);
			
			if (prevCarHistory != null && currCarHistory != null) {
				//分析开关箱异常
				if (currCarHistory.getBoxClose() == prevCarHistory.getBoxClose()) {
					boxState.setBoxCloseTotal(boxState.getBoxCloseTotal() + 1);
					if (boxState.getBoxCloseAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = boxState.getBoxCloseAutoAnalysisdata();
						Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
						Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
						//如果轨迹点之间距离大于500米则是gps数据异常，抛弃这段距离
						Integer distance = GeoUtil.getDistance(p1, p2).intValue();
						if (distance > 500) {
							distance = 0;
						}
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + distance);
						if (autoAnalysisdata.getSpeedMax() == null) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						} else if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					
					if (boxState.getBoxCloseAutoAnalysisdata() != null && 
						boxState.getBoxCloseStartHistory() != null) {
						if (boxState.getBoxCloseAutoAnalysisdata().getViolationsMileage() > Constant.boxCloseMileage && // 如果开关箱状态在超过临界里程时没有变化时则记为一次异常
							boxState.getBoxCloseTotal() >= 600) {
							AutoAnalysisdata autoAnalysisdata = boxState.getBoxCloseAutoAnalysisdata();
							autoAnalysisdata.setCarNumber(carAnalysis.getCarNumber());
							autoAnalysisdata.setDevPhone(carAnalysis.getDevPhone());
							autoAnalysisdata.setEventType(Constant.boxCloseDataType);
							autoAnalysisdata.setGpsPosX(boxState.getBoxCloseStartHistory().getGeo().getX());
							autoAnalysisdata.setGpsPosY(boxState.getBoxCloseStartHistory().getGeo().getY());
							autoAnalysisdata.setGpsSpeed(boxState.getBoxCloseStartHistory().getGpsSpeed());
							autoAnalysisdata.setGpsHeight(boxState.getBoxCloseStartHistory().getGpsHeight());
							autoAnalysisdata.setBoxUp(boxState.getBoxCloseStartHistory().getBoxUp());
							autoAnalysisdata.setBoxEmpty(boxState.getBoxCloseStartHistory().getBoxEmpty());
							autoAnalysisdata.setBoxClose(boxState.getBoxCloseStartHistory().getBoxClose());
							autoAnalysisdata.setInsertTime(new Date());
							Date vioStarttime = new Date(boxState.getBoxCloseStartHistory().getReceiveTime());
							Date vioEndtime = new Date(currCarHistory.getReceiveTime());
							autoAnalysisdata.setVioStarttime(vioStarttime);
							autoAnalysisdata.setVioEndtime(vioEndtime);
							Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
							autoAnalysisdata.setViolationsTime(violationsTime);
							autoAnalysisdata.setRemark("");
					        CloseableHttpResponse httpResponseStart = null;
					        CloseableHttpResponse httpResponseEnd = null;
							try {
								CloseableHttpClient httpclient = HttpClients.createDefault();
							    RequestConfig requestConfig = RequestConfig.custom()
							    		.setSocketTimeout(5000)  
							            .setConnectTimeout(5000)  
							            .setConnectionRequestTimeout(5000)
							            .build();
								URI uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
								        .build();
								HttpGet httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseStart = httpclient.execute(httpget);
								ObjectMapper objectMapper = new ObjectMapper();
					    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							
					    		uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
								        .build();
								httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseEnd = httpclient.execute(httpget);
								objectMapper = new ObjectMapper();
					    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							} catch (URISyntaxException | IOException e) {
								logger.error("", e);
								e.printStackTrace();
							} finally {
								if (httpResponseStart != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
								if (httpResponseEnd != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
							}
							
							//清空开关箱异常数据并持久化违规记录到数据库
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
							boxState.setBoxCloseAutoAnalysisdata(null);
							boxState.setBoxCloseStartHistory(null);
							boxState.setBoxCloseTotal(0);
						}
					}
				} else {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata();
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					boxState.setBoxCloseAutoAnalysisdata(autoAnalysisdata);
					boxState.setBoxCloseStartHistory(currCarHistory);
					boxState.setBoxCloseTotal(1);
				}
				
				//分析重空异常
				if (currCarHistory.getBoxEmpty() == prevCarHistory.getBoxEmpty()) {
					boxState.setBoxEmptyTotal(boxState.getBoxEmptyTotal() + 1);
					if (boxState.getBoxEmptyAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = boxState.getBoxEmptyAutoAnalysisdata();
						Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
						Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
						//如果轨迹点之间距离大于500米则是gps数据异常，抛弃这段距离
						Integer distance = GeoUtil.getDistance(p1, p2).intValue();
						if (distance > 500) {
							distance = 0;
						}
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + distance);
						if (autoAnalysisdata.getSpeedMax() == null) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						} else if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					
					if (boxState.getBoxEmptyAutoAnalysisdata() != null && boxState.getBoxEmptyStartHistory() != null) {
						if (boxState.getBoxEmptyAutoAnalysisdata().getViolationsMileage() > Constant.boxEmptyMileage && // 如果空重车状态在超过临界里程没有变化则记为一次异常
								boxState.getBoxEmptyTotal() >= 600) {
							AutoAnalysisdata autoAnalysisdata = boxState.getBoxEmptyAutoAnalysisdata();
							autoAnalysisdata.setCarNumber(carAnalysis.getCarNumber());
							autoAnalysisdata.setDevPhone(carAnalysis.getDevPhone());
							autoAnalysisdata.setEventType(Constant.boxEmptyDataType);
							autoAnalysisdata.setGpsPosX(boxState.getBoxEmptyStartHistory().getGeo().getX());
							autoAnalysisdata.setGpsPosY(boxState.getBoxEmptyStartHistory().getGeo().getY());
							autoAnalysisdata.setGpsSpeed(boxState.getBoxEmptyStartHistory().getGpsSpeed());
							autoAnalysisdata.setGpsHeight(boxState.getBoxEmptyStartHistory().getGpsHeight());
							autoAnalysisdata.setBoxUp(boxState.getBoxEmptyStartHistory().getBoxUp());
							autoAnalysisdata.setBoxEmpty(boxState.getBoxEmptyStartHistory().getBoxEmpty());
							autoAnalysisdata.setBoxClose(boxState.getBoxEmptyStartHistory().getBoxClose());
							autoAnalysisdata.setInsertTime(new Date());
							Date vioStarttime = new Date(boxState.getBoxEmptyStartHistory().getReceiveTime());
							Date vioEndtime = new Date(currCarHistory.getReceiveTime());
							autoAnalysisdata.setVioStarttime(vioStarttime);
							autoAnalysisdata.setVioEndtime(vioEndtime);
							Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
							autoAnalysisdata.setViolationsTime(violationsTime);
							autoAnalysisdata.setRemark("");
					        CloseableHttpResponse httpResponseStart = null;
					        CloseableHttpResponse httpResponseEnd = null;
							try {
								CloseableHttpClient httpclient = HttpClients.createDefault();
							    RequestConfig requestConfig = RequestConfig.custom()
							    		.setSocketTimeout(5000)  
							            .setConnectTimeout(5000)  
							            .setConnectionRequestTimeout(5000)
							            .build();
								URI uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
								        .build();
								HttpGet httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseStart = httpclient.execute(httpget);
								ObjectMapper objectMapper = new ObjectMapper();
					    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							
					    		uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
								        .build();
								httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseEnd = httpclient.execute(httpget);
								objectMapper = new ObjectMapper();
					    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							} catch (URISyntaxException | IOException e) {
								logger.error("", e);
								e.printStackTrace();
							} finally {
								if (httpResponseStart != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
								if (httpResponseEnd != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
							}
							
							//清空开关箱异常数据并持久化违规记录到数据库
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
							boxState.setBoxEmptyAutoAnalysisdata(null);
							boxState.setBoxEmptyStartHistory(null);
							boxState.setBoxEmptyTotal(0);
						}
					}
				} else {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata();
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					boxState.setBoxEmptyAutoAnalysisdata(autoAnalysisdata);
					boxState.setBoxEmptyStartHistory(currCarHistory);
					boxState.setBoxEmptyTotal(1);
				}
				
				//分析举升异常
				if (currCarHistory.getBoxUp() == prevCarHistory.getBoxUp()) {
					boxState.setBoxUpTotal(boxState.getBoxUpTotal() + 1);
					if (boxState.getBoxUpAutoAnalysisdata() != null) {
						AutoAnalysisdata autoAnalysisdata = boxState.getBoxUpAutoAnalysisdata();
						Point p1 = new Point(prevCarHistory.getGeo().getX(), prevCarHistory.getGeo().getY());
						Point p2 = new Point(currCarHistory.getGeo().getX(), currCarHistory.getGeo().getY());
						//如果轨迹点之间距离大于500米则是gps数据异常，抛弃这段距离
						Integer distance = GeoUtil.getDistance(p1, p2).intValue();
						if (distance > 500) {
							distance = 0;
						}
						autoAnalysisdata.setViolationsMileage(autoAnalysisdata.getViolationsMileage() + distance);
						if (autoAnalysisdata.getSpeedMax() == null) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						} else if (currCarHistory.getGpsSpeed() > autoAnalysisdata.getSpeedMax()) {
							autoAnalysisdata.setSpeedMax(currCarHistory.getGpsSpeed());
						}
					}
					
					if (boxState.getBoxUpAutoAnalysisdata() != null && boxState.getBoxUpStartHistory() != null) {
						if ((currCarHistory.getBoxUp() == 1 && boxState.getBoxUpAutoAnalysisdata().getViolationsMileage() > Constant.boxUpMileage && boxState.getBoxUpTotal() >= 600) ||
							((currCarHistory.getBoxUp() == 2 || currCarHistory.getBoxUp() == 3) && boxState.getBoxUpTotal() > 300)) { // 如果状态持续大于临界里程没有变化或者持续举升达到多次
							AutoAnalysisdata autoAnalysisdata = boxState.getBoxUpAutoAnalysisdata();
							autoAnalysisdata.setCarNumber(carAnalysis.getCarNumber());
							autoAnalysisdata.setDevPhone(carAnalysis.getDevPhone());
							autoAnalysisdata.setEventType(Constant.boxUpDataType);
							autoAnalysisdata.setGpsPosX(boxState.getBoxUpStartHistory().getGeo().getX());
							autoAnalysisdata.setGpsPosY(boxState.getBoxUpStartHistory().getGeo().getY());
							autoAnalysisdata.setGpsSpeed(boxState.getBoxUpStartHistory().getGpsSpeed());
							autoAnalysisdata.setGpsHeight(boxState.getBoxUpStartHistory().getGpsHeight());
							autoAnalysisdata.setBoxUp(boxState.getBoxUpStartHistory().getBoxUp());
							autoAnalysisdata.setBoxEmpty(boxState.getBoxUpStartHistory().getBoxEmpty());
							autoAnalysisdata.setBoxClose(boxState.getBoxUpStartHistory().getBoxClose());
							autoAnalysisdata.setInsertTime(new Date());
							Date vioStarttime = new Date(boxState.getBoxUpStartHistory().getReceiveTime());
							Date vioEndtime = new Date(currCarHistory.getReceiveTime());
							autoAnalysisdata.setVioStarttime(vioStarttime);
							autoAnalysisdata.setVioEndtime(vioEndtime);
							Integer violationsTime = Seconds.secondsBetween(new DateTime(vioStarttime), new DateTime(vioEndtime)).getSeconds();
							autoAnalysisdata.setViolationsTime(violationsTime);
							autoAnalysisdata.setRemark("");
					        CloseableHttpResponse httpResponseStart = null;
					        CloseableHttpResponse httpResponseEnd = null;
							try {
								CloseableHttpClient httpclient = HttpClients.createDefault();
							    RequestConfig requestConfig = RequestConfig.custom()
							    		.setSocketTimeout(5000)  
							            .setConnectTimeout(5000)  
							            .setConnectionRequestTimeout(5000)
							            .build();
								URI uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", autoAnalysisdata.getGpsPosY().toString() + "," + autoAnalysisdata.getGpsPosX().toString())
								        .build();
								HttpGet httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseStart = httpclient.execute(httpget);
								ObjectMapper objectMapper = new ObjectMapper();
					    		Map<?, ?> map = objectMapper.readValue(EntityUtils.toString(httpResponseStart.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark("开始地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							
					    		uri = new URIBuilder()
								        .setScheme("http")
								        .setHost("api.map.baidu.com")
								        .setPath("/geocoder/v2/")
								        .setParameter("ak", "nrWVaLzg4APuvhgFm4x5NDG2")
								        .setParameter("output", "json")
								        .setParameter("pois", "1")
								        .setParameter("location", currCarHistory.getGeo().getY() + "," + currCarHistory.getGeo().getX())
								        .build();
								httpget = new HttpGet(uri);
								httpget.setConfig(requestConfig);
								httpResponseEnd = httpclient.execute(httpget);
								objectMapper = new ObjectMapper();
					    		map = objectMapper.readValue(EntityUtils.toString(httpResponseEnd.getEntity()), HashMap.class);
					    		autoAnalysisdata.setRemark(autoAnalysisdata.getRemark() + "\n结束地点：" + ((Map<?, ?>) map.get("result")).get("formatted_address"));
							} catch (URISyntaxException | IOException e) {
								logger.error("", e);
								e.printStackTrace();
							} finally {
								if (httpResponseStart != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
								if (httpResponseEnd != null) {
									try {
										httpResponseStart.close();
									} catch (IOException e) {
										e.printStackTrace();
									}
								}
							}
							
							//清空开关箱异常数据并持久化违规记录到数据库
							autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
							boxState.setBoxUpAutoAnalysisdata(null);
							boxState.setBoxUpStartHistory(null);
							boxState.setBoxUpTotal(0);
						}
					}
				} else {
					AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata();
					autoAnalysisdata.setEnterpriseName(carEnterpriseNameMap.get(carAnalysis.getCarNumber()));
					autoAnalysisdata.setViolationsMileage(0);
					boxState.setBoxUpAutoAnalysisdata(autoAnalysisdata);
					boxState.setBoxUpStartHistory(currCarHistory);
					boxState.setBoxUpTotal(1);
				}
			}
		}
	}
	
}
